#ifndef BANK_SYSTEM_HH
#define BANK_SYSTEM_HH

#include <string>
#include <map>
#include <vector>
#include <memory>
#include <fstream>
#include <set>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <filesystem>
#include "Customer.hh"
#include "Account.hh"
#include "Transaction.hh"
#include "Utils.hh"

namespace BankSystem
{
    // 银行系统类
    class BankSystem
    {
    private:
        std::map<std::string, std::shared_ptr<Customer>> customers;
        std::map<std::string, std::shared_ptr<Account>> accounts;
        std::vector<std::shared_ptr<Transaction>> allTransactions;
        const std::string ACCOUNTS_FILE = "bank_accounts.dat";
        const std::string CUSTOMERS_FILE = "bank_customers.dat";

        // 验证账号唯一性
        bool isAccountIdUnique(const std::string &accountId) const
        {
            return accounts.find(accountId) == accounts.end();
        }

        // 生成唯一的账号
        std::string generateUniqueAccountId(bool isSavings)
        {
            std::string accountId;
            do
            {
                accountId = Utils::generateAccountNumber(isSavings);
            } while (!isAccountIdUnique(accountId));

            return accountId;
        }

        // 保存账户信息到文件
        bool saveAccountsToFile() const
        {
            std::ofstream file(ACCOUNTS_FILE, std::ios::out);
            if (!file.is_open())
            {
                std::cerr << "Error: Cannot open file for writing accounts." << std::endl;
                return false;
            }

            // 写入账户总数
            file << accounts.size() << std::endl;

            // 保存所有账户数据
            for (const auto &[accountId, account] : accounts)
            {
                // 保存基本账户信息
                file << account->getAccountId() << std::endl;
                file << account->getCustomerName() << std::endl;
                file << account->getBalance() << std::endl;
                file << account->getAccountType() << std::endl;

                // 保存交易记录信息
                const auto &transactions = account->getTransactions();
                file << transactions.size() << std::endl;

                for (const auto &trans : transactions)
                {
                    file << trans->getTransactionId() << std::endl;
                    file << static_cast<int>(trans->getType()) << std::endl;
                    file << trans->getSourceAccountId() << std::endl;
                    file << trans->getDestinationAccountId() << std::endl;
                    file << trans->getAmount() << std::endl;
                    file << trans->getDate() << std::endl;
                    file << trans->getNote() << std::endl;
                }
            }

            file.close();
            return true;
        }

        // 保存客户信息到文件
        bool saveCustomersToFile() const
        {
            std::ofstream file(CUSTOMERS_FILE, std::ios::out);
            if (!file.is_open())
            {
                std::cerr << "Error: Cannot open file for writing customers." << std::endl;
                return false;
            }

            // 写入客户总数
            file << customers.size() << std::endl;

            // 保存所有客户数据
            for (const auto &[name, customer] : customers)
            {
                file << customer->getName() << std::endl;
                file << customer->getSavingsAccount()->getAccountId() << std::endl;
                file << customer->getCheckingAccount()->getAccountId() << std::endl;
            }

            file.close();
            return true;
        }

        // 从文件加载账户信息
        bool loadAccountsFromFile()
        {
            if (!std::filesystem::exists(ACCOUNTS_FILE))
            {
                std::cout << "No existing accounts file found. Starting with empty accounts." << std::endl;
                return true; // 文件不存在不是错误
            }

            std::ifstream file(ACCOUNTS_FILE, std::ios::in);
            if (!file.is_open())
            {
                std::cerr << "Error: Cannot open file for reading accounts." << std::endl;
                return false;
            }

            // 清空现有账户
            accounts.clear();

            // 读取账户总数
            size_t accountCount;
            file >> accountCount;
            file.ignore(); // 忽略换行符

            // 读取每个账户信息
            for (size_t i = 0; i < accountCount; ++i)
            {
                std::string accountId, customerName, accountType;
                double balance;

                std::getline(file, accountId);
                std::getline(file, customerName);
                file >> balance;
                file.ignore(); // 忽略换行符
                std::getline(file, accountType);

                // 根据账户类型创建相应的账户对象
                std::shared_ptr<Account> account;
                if (accountType == "Savings Account")
                {
                    account = std::make_shared<SavingsAccount>(accountId, customerName, balance);
                }
                else if (accountType == "Checking Account")
                {
                    account = std::make_shared<CheckingAccount>(accountId, customerName, balance);
                }
                else
                {
                    std::cerr << "Unknown account type: " << accountType << std::endl;
                    continue;
                }

                // 加载交易记录
                size_t transCount;
                file >> transCount;
                file.ignore(); // 忽略换行符

                for (size_t j = 0; j < transCount; ++j)
                {
                    std::string transId, sourceId, destId, date, note;
                    int typeInt;
                    double amount;

                    std::getline(file, transId);
                    file >> typeInt;
                    file.ignore(); // 忽略换行符
                    std::getline(file, sourceId);
                    std::getline(file, destId);
                    file >> amount;
                    file.ignore(); // 忽略换行符
                    std::getline(file, date);
                    std::getline(file, note);

                    // 创建交易对象并添加到账户
                    auto transaction = std::make_shared<Transaction>(
                        transId, static_cast<TransactionType>(typeInt), sourceId, destId, amount, date, note);
                    account->addTransaction(transaction);

                    // 同时添加到全局交易记录
                    allTransactions.push_back(transaction);
                }

                // 将账户添加到账户映射
                accounts[accountId] = account;
            }

            file.close();
            std::cout << "Successfully loaded " << accounts.size() << " accounts from file." << std::endl;
            return true;
        }

        // 从文件加载客户信息
        bool loadCustomersFromFile()
        {
            if (!std::filesystem::exists(CUSTOMERS_FILE))
            {
                std::cout << "No existing customers file found. Starting with empty customers." << std::endl;
                return true; // 文件不存在不是错误
            }

            std::ifstream file(CUSTOMERS_FILE, std::ios::in);
            if (!file.is_open())
            {
                std::cerr << "Error: Cannot open file for reading customers." << std::endl;
                return false;
            }

            // 清空现有客户
            customers.clear();

            // 读取客户总数
            size_t customerCount;
            file >> customerCount;
            file.ignore(); // 忽略换行符

            // 读取每个客户信息
            for (size_t i = 0; i < customerCount; ++i)
            {
                std::string name, savingsId, checkingId;

                std::getline(file, name);
                std::getline(file, savingsId);
                std::getline(file, checkingId);

                // 获取关联账户
                auto savingsAccount = std::dynamic_pointer_cast<SavingsAccount>(accounts[savingsId]);
                auto checkingAccount = std::dynamic_pointer_cast<CheckingAccount>(accounts[checkingId]);

                if (savingsAccount && checkingAccount)
                {
                    // 创建客户对象
                    auto customer = std::make_shared<Customer>(name, savingsAccount, checkingAccount);
                    customers[name] = customer;
                }
                else
                {
                    std::cerr << "Error: Cannot find accounts for customer " << name << std::endl;
                }
            }

            file.close();
            std::cout << "Successfully loaded " << customers.size() << " customers from file." << std::endl;
            return true;
        }

    public:
        BankSystem()
        {
            // 在构造函数中加载数据
            loadAccountsFromFile();
            loadCustomersFromFile();
        }

        // 析构函数中保存数据
        ~BankSystem()
        {
            saveAccountsToFile();
            saveCustomersToFile();
            std::cout << "Bank system data has been saved." << std::endl;
        }

        // 手动保存数据
        bool saveData()
        {
            bool accountsSaved = saveAccountsToFile();
            bool customersSaved = saveCustomersToFile();

            if (accountsSaved && customersSaved)
            {
                std::cout << "All bank data has been successfully saved." << std::endl;
                return true;
            }
            else
            {
                std::cerr << "Error: Failed to save some bank data." << std::endl;
                return false;
            }
        }

        // 注册新客户
        bool registerCustomer(const std::string &name)
        {
            // 检查客户是否已存在
            if (customers.find(name) != customers.end())
            {
                std::cout << "Error: Customer with name '" << name << "' already exists." << std::endl;
                return false;
            }

            // 为客户创建储蓄账户和支票账户
            std::string savingsId = generateUniqueAccountId(true);
            std::string checkingId = generateUniqueAccountId(false);

            auto savingsAccount = std::make_shared<SavingsAccount>(savingsId, name);
            auto checkingAccount = std::make_shared<CheckingAccount>(checkingId, name);

            // 创建客户对象
            auto customer = std::make_shared<Customer>(name, savingsAccount, checkingAccount);

            // 添加到映射中
            customers[name] = customer;
            accounts[savingsId] = savingsAccount;
            accounts[checkingId] = checkingAccount;

            // 保存到文件
            saveData();

            std::cout << "Customer " << name << " successfully registered!" << std::endl;
            std::cout << "Two bank accounts have been created:" << std::endl;
            std::cout << "- Savings Account: " << savingsId << std::endl;
            std::cout << "- Checking Account: " << checkingId << std::endl;

            return true;
        }

        // 根据名字获取客户
        std::shared_ptr<Customer> getCustomerByName(const std::string &name) const
        {
            auto it = customers.find(name);
            if (it != customers.end())
            {
                return it->second;
            }
            return nullptr;
        }

        // 根据账号获取账户
        std::shared_ptr<Account> getAccountById(const std::string &accountId) const
        {
            auto it = accounts.find(accountId);
            if (it != accounts.end())
            {
                return it->second;
            }
            return nullptr;
        }

        // 获取所有客户
        const std::map<std::string, std::shared_ptr<Customer>> &getAllCustomers() const
        {
            return customers;
        }

        // 获取所有账户
        const std::map<std::string, std::shared_ptr<Account>> &getAllAccounts() const
        {
            return accounts;
        }

        // 记录交易
        void recordTransaction(const std::shared_ptr<Transaction> &transaction)
        {
            allTransactions.push_back(transaction);
            // 在记录交易后保存数据
            saveData();
        }

        // 生成全局交易报告
        // bool generateGlobalTransactionReport() const
        // {
        //     if (allTransactions.empty())
        //     {
        //         std::cout << "No transactions to report." << std::endl;
        //         return false;
        //     }

        //     std::string filename = "transactions_" + Utils::getCurrentDate() + ".txt";
        //     std::ofstream reportFile(filename);

        //     if (!reportFile.is_open())
        //     {
        //         std::cout << "Failed to create report file." << std::endl;
        //         return false;
        //     }

        //     reportFile << "====== Global Transaction Report ======\n";
        //     reportFile << "Date: " << Utils::getCurrentDate() << "\n";
        //     reportFile << "Total Transactions: " << allTransactions.size() << "\n\n";

        //     // 按照交易ID排序（假设ID是按时间顺序生成的）
        //     std::vector<std::shared_ptr<Transaction>> sortedTransactions = allTransactions;
        //     std::sort(sortedTransactions.begin(), sortedTransactions.end(),
        //               [](const std::shared_ptr<Transaction> &a, const std::shared_ptr<Transaction> &b)
        //               {
        //                   return a->getTransactionId() < b->getTransactionId();
        //               });

        //     // 记录已处理的交易ID，以避免重复（因为transfer会被记录两次）
        //     std::set<std::string> processedIds;

        //     for (const auto &transaction : sortedTransactions)
        //     {
        //         if (processedIds.find(transaction->getTransactionId()) == processedIds.end())
        //         {
        //             reportFile << "--------------------------------------\n";
        //             reportFile << transaction->getDetails() << "\n";
        //             processedIds.insert(transaction->getTransactionId());
        //         }
        //     }

        //     reportFile.close();

        //     std::cout << "Report successfully generated as \"" << filename << "\"" << std::endl;
        //     std::cout << "All transactions have been saved in chronological order." << std::endl;

        //     return true;
        // }
        // Modified generateGlobalTransactionReport method for BankSystem.hh
        bool generateGlobalTransactionReport() const
        {
            if (allTransactions.empty())
            {
                std::cout << "No transactions to report." << std::endl;
                return false;
            }

            std::string filename = "transactions_" + Utils::getCurrentDate() + ".txt";
            std::ofstream reportFile(filename);

            if (!reportFile.is_open())
            {
                std::cout << "Failed to create report file." << std::endl;
                return false;
            }

            reportFile << "====== Global Transaction Report ======\n";
            reportFile << "Date: " << Utils::getCurrentDate() << "\n";

            // 按照交易ID排序（假设ID是按时间顺序生成的）
            std::vector<std::shared_ptr<Transaction>> sortedTransactions = allTransactions;
            std::sort(sortedTransactions.begin(), sortedTransactions.end(),
                      [](const std::shared_ptr<Transaction> &a, const std::shared_ptr<Transaction> &b)
                      {
                          return a->getTransactionId() < b->getTransactionId();
                      });

            // 记录已处理的交易ID，以避免重复（因为transfer会被记录两次）
            std::set<std::string> processedIds;

            // 先计算唯一交易数量
            for (const auto &transaction : sortedTransactions)
            {
                processedIds.insert(transaction->getTransactionId());
            }

            // 写入唯一交易数量
            reportFile << "Total Transactions: " << processedIds.size() << "\n\n";

            // 清空以便再次使用
            processedIds.clear();

            for (const auto &transaction : sortedTransactions)
            {
                if (processedIds.find(transaction->getTransactionId()) == processedIds.end())
                {
                    reportFile << "--------------------------------------\n";
                    reportFile << transaction->getDetails() << "\n";
                    processedIds.insert(transaction->getTransactionId());
                }
            }

            reportFile.close();

            std::cout << "Report successfully generated as \"" << filename << "\"" << std::endl;
            std::cout << "All transactions have been saved in chronological order." << std::endl;

            return true;
        }
        // 显示所有银行账户
        void displayAllAccounts() const
        {
            std::vector<std::shared_ptr<Account>> savingsAccounts;
            std::vector<std::shared_ptr<Account>> checkingAccounts;

            for (const auto &[id, account] : accounts)
            {
                if (account->getAccountType() == "Savings Account")
                {
                    savingsAccounts.push_back(account);
                }
                else
                {
                    checkingAccounts.push_back(account);
                }
            }

            std::cout << "\n===== All Bank Accounts =====\n"
                      << std::endl;

            // 显示储蓄账户
            std::cout << "SAVINGS ACCOUNTS:" << std::endl;
            for (size_t i = 0; i < savingsAccounts.size(); ++i)
            {
                const auto &account = savingsAccounts[i];
                std::cout << (i + 1) << ". ID: " << account->getAccountId()
                          << "  |  Owner: " << account->getCustomerName()
                          << "  |  Balance: " << Utils::formatCurrency(account->getBalance())
                          << std::endl;
            }

            std::cout << std::endl;

            // 显示支票账户
            std::cout << "CHECKING ACCOUNTS:" << std::endl;
            for (size_t i = 0; i < checkingAccounts.size(); ++i)
            {
                const auto &account = checkingAccounts[i];
                std::cout << (i + 1) << ". ID: " << account->getAccountId()
                          << "  |  Owner: " << account->getCustomerName()
                          << "  |  Balance: " << Utils::formatCurrency(account->getBalance())
                          << std::endl;
            }

            // 计算统计信息
            double totalBalance = 0.0;
            std::set<std::string> uniqueCustomers;

            for (const auto &[id, account] : accounts)
            {
                totalBalance += account->getBalance();
                uniqueCustomers.insert(account->getCustomerName());
            }

            std::cout << "\nTotal Accounts: " << accounts.size() << std::endl;
            std::cout << "Total Customers: " << uniqueCustomers.size() << std::endl;
            std::cout << "Total Balance: " << Utils::formatCurrency(totalBalance) << std::endl;
        }
    };
}
#endif